package com.easylinkin.linkappapi.security.config.admin;

import com.alibaba.fastjson.JSON;
import com.easylinkin.bases.redis.util.RedisUtil;
import com.easylinkin.linkappapi.operatelog.entity.CommonOperateLog;
import com.easylinkin.linkappapi.operatelog.service.CommonOperateLogService;
import com.easylinkin.linkappapi.security.config.LoginCountCheck;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.util.Assert;
import site.morn.boot.web.Responses;
import site.morn.rest.RestBuilders;
import site.morn.rest.RestMessage;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

import static com.easylinkin.linkappapi.security.constant.admin.UserConstant.ADMIN_LOGIN_VERIFICATION_CODE_PREFIX;


/**
 * 管理端 用户名+验证码登录
 *
 * @author tongjie
 */
public class AdminUserPhoneLoginAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private static final String USERNAME = "username";
    private static final String PASSWORD = "password";
    private static final String VERIFICATION_CODE = "verificationCode";

    @Autowired
    private RedisUtil redisUtil;    
    @Resource
    private LoginCountCheck loginCountCheck;    
    @Resource
    private CommonOperateLogService commonOperateLogService;
    @Value("${linkapp.isEnableVerificationCode:true}")
    private Boolean isEnableVerificationCode;

    public AdminUserPhoneLoginAuthenticationFilter() {
        super(new AntPathRequestMatcher("/adminPhoneLogin", "POST"));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String verificationCode = request.getParameter(VERIFICATION_CODE);
        String password = request.getParameter(PASSWORD);
        String username = request.getParameter(USERNAME);
        try {
            Assert.hasLength(username, "用户名参数为空");
            Assert.hasLength(password, "密码参数为空");
            if(isEnableVerificationCode == null || isEnableVerificationCode == true){
                Assert.hasLength(verificationCode, "验证码参数为空");
                //从缓存取到验证码并校验
                Object obj = redisUtil.get(ADMIN_LOGIN_VERIFICATION_CODE_PREFIX + username);
                Assert.isTrue(obj != null && verificationCode.equalsIgnoreCase(obj.toString()), "用户名错误，或验证码错误或失效");
            }
            Assert.hasLength(username,"找不到相应用户名");
            request.setAttribute(USERNAME, username);
            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
            // Allow subclasses to set the "details" property
            authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
            return super.getAuthenticationManager().authenticate(authRequest);
        } catch (Exception e) {
            if (username != null) {
                loginCountCheck.afterLoginHandler(false, username);
            }
            RestMessage message = RestBuilders.failureMessage("login.failure").setMessage(e.getMessage());
            Responses.standard(response).respond(message);

            CommonOperateLog commonOperateLog = new CommonOperateLog();
            commonOperateLog.setTenantId("operation_management_user");
            commonOperateLog.setModuleName("登录");
            commonOperateLog.setContent("管理端登录失败");
            commonOperateLog.setUserAccount(username);
            commonOperateLog.setResultContent(JSON.toJSONString(message));
            commonOperateLog.setCreateTime(new Date()).setResult(false);
            commonOperateLogService.addLog(commonOperateLog);
            return null;
        }



    }

    @Override
    public void setAuthenticationManager(AuthenticationManager authenticationManager) {
        super.setAuthenticationManager(authenticationManager);
    }

}
